package com.mikao.service.impl;

import com.mikao.config.CdnProperties;
import com.mikao.dao.*;
import com.mikao.dto.bo.*;
import com.mikao.dto.vo.*;
import com.mikao.entity.Goods;
import com.mikao.entity.OfferPrice;
import com.mikao.entity.UserSellOrder;
import com.mikao.entity.UserTree;
import com.mikao.mybatis.mapper.*;
import com.mikao.service.GoodsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.criteria.Predicate;
import javax.transaction.Transactional;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author KennyDavid
 */

@Slf4j
@Service
public class GoodsServiceImpl implements GoodsService {


    @Value("${cdn.baseUrl}")
    private String cdn;
    private GoodsDao goodsDao;
    private final CdnProperties cdnProperties;
    private UserTreeMapper userTreeMapper;
    private UserTreeDao userTreeDao;
    private RecycleTreeOrderMapper recycleTreeOrderMapper;
    private RecycleOrderDao recycleOrderDao;
    private RecycleFruitOrderMapper recycleFruitOrderMapper;
    private OfferPriceDao offerPriceDao;
    private FruitMarketMapper fruitMarketMapper;
    private UserSellOrderDao userSellOrderDao;
    private TreeMarketMapper treeMarketMapper;
    private UserDao userDao;

    public GoodsServiceImpl(GoodsDao goodsDao, CdnProperties cdnProperties, UserTreeMapper userTreeMapper, UserTreeDao userTreeDao, RecycleTreeOrderMapper recycleTreeOrderMapper, RecycleOrderDao recycleOrderDao, RecycleFruitOrderMapper recycleFruitOrderMapper, OfferPriceDao offerPriceDao, FruitMarketMapper fruitMarketMapper, UserSellOrderDao userSellOrderDao, TreeMarketMapper treeMarketMapper, UserDao userDao) {
        this.goodsDao = goodsDao;
        this.cdnProperties = cdnProperties;
        this.userTreeMapper = userTreeMapper;
        this.userTreeDao = userTreeDao;
        this.recycleTreeOrderMapper = recycleTreeOrderMapper;
        this.recycleOrderDao = recycleOrderDao;
        this.recycleFruitOrderMapper = recycleFruitOrderMapper;
        this.offerPriceDao = offerPriceDao;
        this.fruitMarketMapper = fruitMarketMapper;
        this.userSellOrderDao = userSellOrderDao;
        this.treeMarketMapper = treeMarketMapper;
        this.userDao = userDao;
    }

    @Override
    public RspDataTableDto<GoodsDto> goodsList(ReqDataTableDto dataTableDTO, String nameOrMobile, String dateRangePicker, Long type) {
        Date start = null;
        Date end = null;
        if (dateRangePicker != null) {
            String[] time = dateRangePicker.split(" - ");
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            try {
                start = simpleDateFormat.parse(time[0]);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            try {
                end = simpleDateFormat.parse(time[1]);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            long time1 = start != null ? start.getTime() : 0;
            long time2 = end != null ? end.getTime() : 0;
            if (time1 == time2) {
                if (end != null) {
                    end.setTime(time2 + 86400000 - 1);
                }
            }
        }
        Date finalStart = start;
        Date finalEnd = end;

        List<GoodsDto> dtos = new ArrayList<>();
        PageRequest pageRequest = new PageRequest(dataTableDTO.getPage(), dataTableDTO.getLength(),
                new Sort(Sort.Direction.DESC, "createTime"));
        Page<Goods> page = goodsDao.findAll((root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            Predicate p2;
            if (StringUtils.hasText(dateRangePicker)) {
                Predicate p = criteriaBuilder.between(root.get("createTime"), finalStart, finalEnd);
                predicates.add(p);
            }
            if (StringUtils.hasText(nameOrMobile)) {
                Predicate p1 = criteriaBuilder.like(root.get("name"), "%" + nameOrMobile + "%");
                predicates.add(p1);
            }
            if (!ObjectUtils.isEmpty(type)) {
                p2 = criteriaBuilder.equal(root.get("type").as(Long.class), type);
                predicates.add(p2);
            }
            Predicate p3 = criteriaBuilder.equal(root.get("isDiscount").as(Boolean.class), false);
            predicates.add(p3);
            return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
        }, pageRequest);

        GoodsDto goodsDto;
        for (Goods goods : page.getContent()) {
            goodsDto = new GoodsDto();
            BeanUtils.copyProperties(goods, goodsDto);
            goodsDto.setCoverImage(goods.getCoverImage());
            dtos.add(goodsDto);
        }
        return new RspDataTableDto<>(dataTableDTO.getDraw(), page.getTotalElements(), dtos);
    }

    @Override
    public void saveGoods(GoodsForm goodsForm, MultipartFile coverImage) {
        Goods goods;
        if (ObjectUtils.isEmpty(goodsForm.getId())) {
            goods = new Goods();
        } else {
            goods = goodsDao.findOne(goodsForm.getId());
        }

        if (!ObjectUtils.isEmpty(coverImage)) {
            //上传封面图片
            MultipartFile file = coverImage;
            File f = new File(cdnProperties.getBasePath());
            if (!f.exists()) {
                f.mkdirs();
            }

            String oldName = file.getOriginalFilename();
            String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));

            File newFile = new File(f.getAbsolutePath(), newName);
            try {
                newFile.createNewFile();
                file.transferTo(newFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
            goods.setCoverImage(cdn + newName);
        }
        log.info(String.valueOf(goodsForm.getImages()));
        BeanUtils.copyProperties(goodsForm, goods);

        String[] split = goodsForm.getImages().split(",");
        StringBuilder ss = new StringBuilder();
        for (String s : split) {
            String s1 = cdn + s;
            ss.append(s1).append(",");
        }
        goods.setImages(String.valueOf(ss).substring(0, String.valueOf(ss).length() - 1));
        if (ObjectUtils.isEmpty(goodsForm.getStatus())) {
            goods.setStatus(false);
        }
        if (6 == goodsForm.getType()) {
            goods.setPoint(Integer.valueOf(goodsForm.getPrice()));
            goods.setIsPoint(true);
        }
        goods.setIsDiscount(false);
        goods.setSource(1);
        goodsDao.saveAndFlush(goods);
    }

    @Override
    public void removeGoods(Long aLong) {
        goodsDao.delete(aLong);
    }

    @Override
    @Transactional(rollbackOn = Exception.class)
    public boolean updateGoodsStatus(Boolean status, Long[] id) {
        List<Long> ids = new ArrayList<>();
        Collections.addAll(ids, id);
        goodsDao.updateGoodsStatus(ids, status);
        return true;
    }

    @Override
    public ImageDto saveImage(MultipartFile image) {
        List<String> list = new ArrayList<>();
        if (!ObjectUtils.isEmpty(image)) {
            MultipartFile file = image;
            File f = new File(cdnProperties.getBasePath());
            if (!f.exists()) {
                f.mkdirs();
            }
            String oldName = file.getOriginalFilename();
            System.out.println(oldName);
            String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
            System.out.println(newName);
            File newFile = new File(f.getAbsolutePath(), newName);
            try {
                newFile.createNewFile();
                file.transferTo(newFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
            list.add(cdn + newName);
        }
        return new ImageDto(list.toArray(new String[list.size()]));
    }

    @Override
    public ImagesDto uploadFile(MultipartFile[] images) {
        ImagesDto imageDto = new ImagesDto();
        List<String> urls = new ArrayList<>();
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String today = sdf.format(new Date());
            for (MultipartFile file : images) {
                java.io.File f = new java.io.File(cdnProperties.getBasePath() + java.io.File.separator + today);
                if (!f.exists()) {
                    f.mkdirs();
                }

                String oldName = file.getOriginalFilename();
                String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));

                java.io.File newFile = new java.io.File(f.getAbsolutePath(), newName);
                newFile.createNewFile();
                file.transferTo(newFile);
                if (ObjectUtils.isEmpty(newFile)) {
                    return null;
                }
                urls.add(today + "/" + newName);
                log.info("轮播图" + today + "/" + newName);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        log.info(String.valueOf(urls));
        imageDto.setData(urls);
        return imageDto;
    }

    @Override
    public RspDataTableDto<TreeDto> treeList(ReqDataTableDto reqDataTableDto, TreeForm treeForm) {
        List<TreeDto> list = userTreeMapper.treeList(treeForm);
        Goods goods;
        long l;
        for (TreeDto treeDto : list) {
            goods = goodsDao.findOne(treeDto.getGoodsId());
            l = (treeDto.getCreateTime().getTime() - goods.getCreateTime().getTime()) / (1000 * 3600 * 24);
            treeDto.setDays(l);
        }
        return new RspDataTableDto<>(treeForm.getDraw(), userTreeDao.count(), list);
    }

    @Override
    public void addTree(TreeEditForm treeEditForm) {
        UserTree one = userTreeDao.findOne(treeEditForm.getId());
        one.setDetail(treeEditForm.getDetail());
        if (!ObjectUtils.isEmpty(treeEditForm.getWeight())) {
            one.setWeight(treeEditForm.getWeight());
            one.setType(2);
        }
        userTreeDao.saveAndFlush(one);
    }

    @Override
    public RspDataTableDto<TreeOrderDto> recycleTreeOrder(ReqDataTableDto reqDataTableDto, TreeForm treeForm) {
        List<TreeOrderDto> treeOrderDtos = recycleTreeOrderMapper.recycleTreeOrder(treeForm);
        Goods goods;
        long l;
        for (TreeOrderDto treeOrderDto : treeOrderDtos) {
            goods = goodsDao.findOne(treeOrderDto.getGoodsId());
            l = (treeOrderDto.getCreateTime().getTime() - goods.getCreateTime().getTime()) / (1000 * 3600 * 24);
            treeOrderDto.setDays(l);
        }
        return new RspDataTableDto<>(treeForm.getDraw(), recycleOrderDao.findCountTreeorder(), treeOrderDtos);
    }

    @Override
    public void addTreePrice(TreePriceForm treePriceForm) {
        UserSellOrder one = recycleOrderDao.findOne(treePriceForm.getId());
        one.setRecyclePrice(treePriceForm.getRecyclePrice());
        one.setStatus(2);
        recycleOrderDao.saveAndFlush(one);
    }

    @Override
    public RspDataTableDto<FruitOrderDto> recycleFruitOrder(ReqDataTableDto reqDataTableDto, TreeForm treeForm) {
        List<FruitOrderDto> fruitOrderDtos = recycleFruitOrderMapper.recycleFruitOrder(treeForm);
        for (FruitOrderDto dto : fruitOrderDtos) {
            OfferPrice one = offerPriceDao.findOne((long) 1);
            dto.setPrice(one.getPrice());
            dto.setAllPrice(dto.getPrice() * dto.getWeight());
        }
        return new RspDataTableDto<>(reqDataTableDto.getDraw(), (long) fruitOrderDtos.size(), fruitOrderDtos);
    }

    @Override
    public RspDataTableDto<FruitMarketDto> fruitMarketList(ReqDataTableDto reqDataTableDto, TreeForm treeForm) {
        List<FruitMarketDto> list = fruitMarketMapper.fruitMarketList(treeForm);
        return new RspDataTableDto<>(treeForm.getDraw(), (long) list.size(), list);
    }

    @Override
    public void sendFruitMarket(SendForm sendForm) {
        UserSellOrder one = userSellOrderDao.findOne(sendForm.getId());
        one.setExpressCode(sendForm.getExpressCode());
        userSellOrderDao.saveAndFlush(one);
    }

    @Override
    public RspDataTableDto<TreeMarketDto> treeMarketList(ReqDataTableDto reqDataTableDto, TreeForm treeForm) {
        List<TreeMarketDto> list = treeMarketMapper.treeMarketList(treeForm);
        Goods goods;
        long l;
        for (TreeMarketDto treeMarketDto : list) {
            goods = goodsDao.findOne(treeMarketDto.getGoodsId());
            l = (treeMarketDto.getCreateTime().getTime() - goods.getCreateTime().getTime()) / (1000 * 3600 * 24);
            treeMarketDto.setDays(l);
        }
        return new RspDataTableDto<>(reqDataTableDto.getDraw(), (long) list.size(), list);
    }
}
